package com.lanchetech.admin.service.impl;


import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.StringUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lanchetech.admin.service.VipService;
import com.lanchetech.bean.request.BonusCountReq;
import com.lanchetech.bean.request.IdentityReq;
import com.lanchetech.bean.request.PageReq;
import com.lanchetech.bean.request.VipReq;
import com.lanchetech.bean.response.BasePageResp;
import com.lanchetech.bean.response.BaseResp;
import com.lanchetech.bean.response.ResultData;
import com.lanchetech.bean.util.PageHelpUtil;
import com.lanchetech.bean.vo.*;
import com.lanchetech.common.enums.*;
import com.lanchetech.common.exception.ResultCodeException;
import com.lanchetech.dao.*;
import com.lanchetech.entity.*;
import com.lanchetech.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class VipServiceImpl implements VipService {


    @Autowired
    UserMapper userMapper;

    @Autowired
    DaoService daoService;

    @Autowired
    CommissionRecordMapper commissionRecordMapper;

    @Autowired
    ConsumptionRecordMapper consumptionRecordMapper;

    @Autowired
    ConsumptionService consumptionService;

    @Autowired
    ConsumptionAmountMapper consumptionAmountMapper;

    @Autowired
    HonorMapper honorMapper;

    @Autowired
    GroupService groupService;

    @Autowired
    LevelService levelService;

    @Autowired
    IdentityMapper identityMapper;

    @Autowired
    UserCommissionMapper userCommissionMapper;

    @Autowired
    BonusCountMapper bonusCountMapper;

    @Autowired
    UserRelationshipMapper userRelationshipMapper;

    @Autowired
    CardFlowMapper cardFlowMapper;

    @Autowired
    OrdersMapper ordersMapper;

    @Autowired
    HipoConfigMapper hipoConfigMapper;

    @Autowired
    AdFlowMapper adFlowMapper;

    @Autowired
    RewardQueueMapper rewardQueueMapper;

    @Autowired
    UserGroupMapper userGroupMapper;

    @Autowired
    UserInfoMapper userInfoMapper;

    @Autowired
    CommissionService commissionService;

    @Override
    public ResultData<BasePageResp<IdentityVO>> getIdentityPage(IdentityReq req) {

        if (!StringUtils.isEmpty(req.getPhone())) {
            User user = userMapper.findOneByUsername(req.getPhone());
            req.setUserId(user == null ? 0L : user.getId());
        }

        if (!StringUtils.isEmpty(req.getNickname())) {
            User user = userMapper.findOneByNicknameLike(req.getNickname());
            req.setUserId(user == null ? 0L : user.getId());
        }


        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<IdentityVO> list = identityMapper.findAllPage(req);

        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(IdentityVO::getUserId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                item.setAvatar(userMap.get(item.getUserId()).getAvatar());
                item.setNickname(userMap.get(item.getUserId()).getNickname());
            });
        }

        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public BaseResp updateUserLevel(Long userId, Integer level) {
        groupService.updateUserLevel(level, userId);
        return new BaseResp();
    }

    @Override
    public BaseResp createUserLevel(VipReq req) {
        User user = userMapper.findOneByUsername(req.getPhone());

        if (user == null) {
            return new BaseResp(ResultCode.ACCT_NOT_EXIST);
        }
        if (UserStatusEnum.BAN.getStatus().equals(user.getStatus())) {
            return new BaseResp(ResultCode.USER_BAN);
        }
        switch (UserLevelEnum.getByLevel(req.getLevel())) {
            case CUSTOMER:
                levelService.addOneRecommend(user, req.getIsBuyer());
                break;
            case MEMBER_L1:
                levelService.addOneMember(user, req.getIsBuyer(), req.getMemberState());
                break;
            case PARTNER_L1:
                // 允许重复设置合伙人
                levelService.addOnePartner(user, req.getIsBuyer());
                break;
            case SHAREHOLDER_L1:
                if (user.getLevel() >= UserLevelEnum.SHAREHOLDER_L1.getLevel()) {
                    return new BaseResp(ResultCode.IS_OVER_SHAREHOLDER);
                }
                levelService.addOneShareholder(user, req.getIsBuyer());
                break;
            case SHAREHOLDER_L2:
                // 如果小于董事身份，则先给他一个董事身份
                if (user.getLevel() < UserLevelEnum.SHAREHOLDER_L1.getLevel()) {
                    levelService.addOneShareholder(user, req.getIsBuyer());
                }

                // 然后直接晋升为副总裁
                identityMapper.updateLevelAndShareholderLevelByUserId(UserLevelEnum.SHAREHOLDER_L2.getLevel(), UserLevelEnum.SHAREHOLDER_L2.getLevel(), user.getId());
                updateUserLevel(user.getId(), UserLevelEnum.SHAREHOLDER_L2.getLevel());

                break;
            case SHAREHOLDER_L3:
                // 如果小于董事身份，则先给他一个董事身份
                if (user.getLevel() < UserLevelEnum.SHAREHOLDER_L1.getLevel()) {
                    levelService.addOneShareholder(user, req.getIsBuyer());
                }

                // 然后直接晋升为总裁
                identityMapper.updateLevelAndShareholderLevelByUserId(UserLevelEnum.SHAREHOLDER_L3.getLevel(), UserLevelEnum.SHAREHOLDER_L3.getLevel(), user.getId());
                updateUserLevel(user.getId(), UserLevelEnum.SHAREHOLDER_L3.getLevel());
                break;
            case PARTNER_DIRECTOR:
                levelService.addOneMember(user, req.getIsBuyer(), MemberStateEnum.SUPER.getType());
                levelService.addOnePartner(user, req.getIsBuyer());
                levelService.addOneShareholder(user, req.getIsBuyer());
                Identity identity = identityMapper.findOneByUserId(user.getId());
                identity.setDirector(DirectorEnum.DIRECTOR.getType());
                identity.setPartnerAccount(identity.getPartnerAccount() + Integer.valueOf(daoService.getHipoConfigValue(HipoConfigEnum.DIRECTOR_PARTNER_ACCOUNT_COUNT.getConfig())));
                identity.setAreaAccount(identity.getAreaAccount());
                identityMapper.updateByPrimaryKeySelective(identity);
                break;
            case COMPANY:
                Identity identity2 = identityMapper.findOneByUserId(user.getId());
                identity2.setShareholderState(ShareholderStateEnum.COMPANY.getType());
                identityMapper.updateByPrimaryKeySelective(identity2);
                break;
            default:
                break;
        }

        // 保存用户的身份信息到userInfo
        UserInfo userInfo = UserInfo.builder()
                .idCard(req.getIdCard())
                .realName(req.getName())
                .userId(user.getId())
                .updatedAt(new Date())
                .build();
        userInfoMapper.updateIdCardAndRealNameAndUpdatedAtByUserId(userInfo);

        // 如果是购买类型的，则发放分红和奖励等
        if (IsBuyerEnum.BUYER.getType().equals(req.getIsBuyer())) {
            commissionService.prepareIdentityCommission(user, IdentityTypeEnum.getIdentityTypeByLevel(req.getLevel()));
        }

        return new BaseResp();
    }

    @Override
    public BaseResp deleteIdentity(Long id) {
        // 此身份记录完全删除，此用户等级回到游客等级。
        Identity identity = identityMapper.selectByPrimaryKey(id);
        levelService.updateUserLevel(identity.getUserId(), UserLevelEnum.CUSTOMER.getLevel());
        identityMapper.deleteByPrimaryKey(id);

        // 此用户拥有的所有冻结佣金将全部扣除
        userCommissionMapper.updateStatusBySuperiorIdAndStatus(UserCommissionStatusEnum.MANAGER.getStatus(), identity.getUserId(), UserCommissionStatusEnum.FREEZE.getStatus());

        // 和此身份相关的冻结佣金全部扣除
        userCommissionMapper.updateStatusBySubordinateIdAndStatus(UserCommissionStatusEnum.MANAGER.getStatus(), identity.getUserId(), UserCommissionStatusEnum.FREEZE.getStatus());

        // 对应的董事计数减1，如果已经为0，则减至负数。
        if (identity.getType().equals(IdentityTypeEnum.MEMBER.getType())) {
            BonusCount bonusCount = bonusCountMapper.findOneByRewardType(RewardTypeEnum.MEMBER_L4.getType());
            bonusCount.setCount(bonusCount.getCount() - 1);
            bonusCountMapper.updateByPrimaryKeySelective(bonusCount);
        }

        if (identity.getType().equals(IdentityTypeEnum.PARTNER.getType())) {
            BonusCount bonusCount = bonusCountMapper.findOneByRewardType(RewardTypeEnum.PARTNER_L4.getType());
            bonusCount.setCount(bonusCount.getCount() - 1);
            bonusCountMapper.updateByPrimaryKeySelective(bonusCount);
        }

        if (identity.getType().equals(IdentityTypeEnum.SHAREHOLDER.getType())) {
            BonusCount bonusCount = bonusCountMapper.findOneByRewardType(RewardTypeEnum.SHAREHOLDER_L4.getType());
            bonusCount.setCount(bonusCount.getCount() - 1);
            bonusCountMapper.updateByPrimaryKeySelective(bonusCount);
        }

        UserRelationship userRelationship = userRelationshipMapper.findOneBySubordinateId(identity.getUserId());
        if (userRelationship != null) {
            // 上下级关系链变为未绑定状态
            userRelationship.setStatus(RelationshipStatusEnum.NOT_BIND.getStatus());
            userRelationshipMapper.updateByPrimaryKeySelective(userRelationship);
        }

        // 嗨币和广告余额全部扣除
        User user = userMapper.selectByPrimaryKey(identity.getUserId());
        if (user.getCardPoint().compareTo(BigDecimal.ZERO) > 0) {
            cardFlowMapper.insert(CardFlow.builder()
                    .userId(identity.getUserId())
                    .amount(user.getCardPoint())
                    .tradeType(CardTradeTypeEnum.SYSTEM_DEDUCT.getTradeType())
                    .type(CardTradeTypeEnum.SYSTEM_DEDUCT.getType())
                    .cardPoint(BigDecimal.ZERO)
                    .createdAt(new Date())
                    .build());
            userMapper.updateCardPointById(BigDecimal.ZERO, identity.getUserId());
        }

        if (user.getAdPoint().compareTo(BigDecimal.ZERO) > 0) {
            adFlowMapper.insert(AdFlow.builder()
                    .userId(identity.getUserId())
                    .amount(user.getAdPoint())
                    .tradeType(AdFlowTradeTypeEnum.SYSTEM_DEDUCT.getTradeType())
                    .type(AdFlowTradeTypeEnum.SYSTEM_DEDUCT.getType())
                    .adPoint(BigDecimal.ZERO)
                    .build());
            userMapper.updateAdPointById(BigDecimal.ZERO, identity.getUserId());
        }

        // 解散他的团队
        userGroupMapper.deleteByCaptainId(user.getId());

        // 退出他所在的团队
        userGroupMapper.deleteByMemberId(user.getId());

        return new BaseResp();
    }

    @Override
    public BaseResp createConsumptionRecord(ConsumptionRecord req) {
        if (ConsumptionRecordTypeEnum.MANAGER_SUB.getRecordType().equals(req.getRecordType()) || ConsumptionRecordTypeEnum.MANAGER_ADD.getRecordType().equals(req.getRecordType())) {
            consumptionService.updateConsumptionAmount(req);
        }
        req.setCreatedAt(new Date());
        consumptionRecordMapper.insert(req);
        return new BaseResp();
    }

    @Override
    public BaseResp banUserForCommission(Long userId, Integer status) {
        userMapper.updateStatusById(status, userId);
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<ConsumptionAmountVO>> getConsumptionAmountPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<ConsumptionAmountVO> list = consumptionAmountMapper.findAllPage(req);

        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(ConsumptionAmount::getUserId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                item.setAvatar(userMap.get(item.getUserId()).getAvatar());
                item.setNickname(userMap.get(item.getUserId()).getNickname());
            });
        }

        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<BasePageResp<ConsumptionRecordVO>> getConsumptionRecordPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<ConsumptionRecordVO> list = consumptionRecordMapper.findAllPage(req);

        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(ConsumptionRecordVO::getUserId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                item.setAvatar(userMap.get(item.getUserId()).getAvatar());
                item.setNickname(userMap.get(item.getUserId()).getNickname());
            });
        }

        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<BasePageResp<HonorVO>> getHonorPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<Honor> list = honorMapper.findAllPage(req);

        List<HonorVO> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(Honor::getUserId).collect(Collectors.toList()));

            list.stream().forEach(item -> {
                HonorVO vo = new HonorVO();
                BeanUtils.copyProperties(item, vo);
                vo.setAvatar(userMap.get(item.getUserId()).getAvatar());
                vo.setNickname(userMap.get(item.getUserId()).getNickname());
                result.add(vo);
            });
        }

        return PageHelpUtil.buildPage(result, page);
    }

    @Override
    public BaseResp deleteHonor(Long id) {
        honorMapper.deleteByPrimaryKey(id);
        return new BaseResp();
    }

    @Override
    public BaseResp editHonor(Honor req) {

        if (req.getId() == null) {
            req.setCreatedAt(new Date());
            honorMapper.insert(req);
        } else {
            honorMapper.updateByPrimaryKeySelective(req);
        }

        return new BaseResp();
    }

    @Override
    public ResultData<List<BonusCount>> getBonusCountList() {
        return new ResultData<>(bonusCountMapper.findAll());
    }

    @Override
    public ResultData<BasePageResp<BonusCountVO>> getBonusCountPage(BonusCountReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<BonusCountVO> list = bonusCountMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, Spu> spuMap = daoService.getSpuMap(list.stream().map(BonusCountVO::getSpuId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                if (spuMap.containsKey(item.getSpuId())) {
                    item.setSpuImage(spuMap.get(item.getSpuId()).getMainImage());
                    item.setSpuName(spuMap.get(item.getSpuId()).getName());
                }
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<BasePageResp<CardFlowVO>> getCardFlowPage(PageReq req) {

        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<CardFlowVO> list = cardFlowMapper.findAllPage(req);

        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(CardFlowVO::getUserId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                item.setAvatar(userMap.get(item.getUserId()).getAvatar());
                item.setNickname(userMap.get(item.getUserId()).getNickname());
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<CountOrderVO> countOrder(PageReq req) {
        return new ResultData<>(ordersMapper.countByCreatedAtAndStatus(req));
    }

    @Override
    public ResultData<BasePageResp<RewardQueueVO>> getRewardQueuePage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<RewardQueueVO> list = rewardQueueMapper.findAllPage(req);
        if (!list.isEmpty()) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(RewardQueueVO::getUserId).collect(Collectors.toList()));
            Map<Long, Spu> spuMap = daoService.getSpuMap(list.stream().map(RewardQueueVO::getSpuId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                if (item.getType().equals(RewardQueueTypeEnum.SPU.getType())) {
                    item.setSpuMainImage(spuMap.get(item.getSpuId()).getMainImage());
                    item.setSpuName(spuMap.get(item.getSpuId()).getName());
                }
                item.setUserNickname(userMap.get(item.getUserId()).getNickname());
                item.setUserAvatar(userMap.get(item.getUserId()).getAvatar());
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public BaseResp issueRewardQueue(Long id, BigDecimal amount) {
        RewardQueue rewardQueue = rewardQueueMapper.selectByPrimaryKey(id);

        if (ToggleEnum.ON.getStatus().equals(rewardQueue.getQueueStatus()) && ToggleEnum.OFF.getStatus().equals(rewardQueue.getRewardStatus())) {
            Integer level = rewardQueue.getLevel();
            Byte identityType;
            Byte type;
            if (UserLevelEnum.MEMBER_L4.getLevel().equals(level)) {
                type = UserCommissionTypeEnum.MEMBER_L4_BONUS.getType();
                identityType = IdentityTypeEnum.MEMBER.getType();
            } else if (UserLevelEnum.PARTNER_L4.getLevel().equals(level)) {
                type = UserCommissionTypeEnum.PARTNER_L4_BONUS.getType();
                identityType = IdentityTypeEnum.PARTNER.getType();
            } else if (UserLevelEnum.SHAREHOLDER_L4.getLevel().equals(level)) {
                type = UserCommissionTypeEnum.SHAREHOLDER_L4_BONUS.getType();
                identityType = IdentityTypeEnum.SHAREHOLDER.getType();
            } else {
                return new BaseResp(ResultCode.FAIL);
            }

            rewardQueueMapper.updateRewardStatusAndUpdateAtById(ToggleEnum.ON.getStatus(), new Date(), id);

            userCommissionMapper.insert(UserCommission.builder()
                    .superiorId(rewardQueue.getUserId())
                    .commission(amount)
                    .subordinateId(rewardQueue.getUserId())
                    .type(type)
                    .status(UserCommissionStatusEnum.ISSUED.getStatus())
                    .freezeTime(new Date())
                    .createdAt(new Date())
                    .updatedAt(new Date())
                    .amount(BigDecimal.ZERO)
                    .identityType(identityType)
                    .businessType(UserCommissionBusinessTypeEnum.USER.getType())
                    .build());
            return new BaseResp();
        } else {
            return new BaseResp(ResultCode.FAIL);
        }
    }

}